/**
 * This file is part of 1genia trampoline
 * Copyright (C) 2007 - 2008 1genia (contact@1genia.com)
 *
 * This library is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; version 3 of the License. 
 *
 * This library is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details. 
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; see the file COPYING.TXT.  If not,
 * write to the Free Software Foundation, Inc., 51 Franklin Street,
 * Fifth Floor, Boston, MA 02110-1301, USA. 
 **/
package com.genia.toolbox.form.editor.gui.view.settings.panel;

import java.awt.CardLayout;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.List;

import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.ListSelectionModel;
import javax.swing.event.DocumentListener;
import javax.swing.event.TableModelListener;

import com.genia.toolbox.basics.editor.gui.AbstractGUI;
import com.genia.toolbox.basics.editor.gui.panel.AbstractPanel;
import com.genia.toolbox.basics.editor.model.document.VariableModel;
import com.genia.toolbox.form.editor.gui.FormEditorGUI;
import com.genia.toolbox.form.editor.gui.view.settings.table.VariableCellEditor;
import com.genia.toolbox.form.editor.gui.view.settings.table.VariableCellRenderer;
import com.genia.toolbox.form.editor.gui.view.settings.table.VariableTableModel;
import com.genia.toolbox.form.editor.message.Messages;
import com.genia.toolbox.web.gwt.form.client.form.impl.EnumDescriptableValuedItemEntryListImpl;
import com.genia.toolbox.web.gwt.form.server.spring.factory.EnumDescriptableValuedItemEntryListFactory;

/**
 * The item entry settings panel.
 */
@SuppressWarnings("serial")
public class ItemEntrySettingsPanel
    extends AbstractPanel<FormEditorGUI>
    implements ActionListener
{

  /**
   * The enum label type.
   */
  private JLabel labelEnumType = null;

  /**
   * The type of entry combo box.
   */
  private JComboBox comboEntryType = null;

  /**
   * The enum label.
   */
  private JLabel labelEnum = null;

  /**
   * The entry name label.
   */
  private JTextField textEnum = null;

  /**
   * The entry label.
   */
  private JLabel labelEntry = null;

  /**
   * The entry field.
   */
  private JLabel labelEntryName = null;

  /**
   * The entry name label.
   */
  private JTextField textEntryName = null;

  /**
   * The add entry button.
   */
  private JButton buttonAddEntry = null;

  /**
   * The delete entry button.
   */
  private JButton buttonDeleteSelectedEntry = null;

  /**
   * The entries table.
   */
  private JTable tableEntries = null;

  /**
   * The table entries model.
   */
  private VariableTableModel tableEntriesModel = null;

  /**
   * The card layout.
   */
  private CardLayout layout = null;

  /**
   * The enum panel name.
   */
  private final static String PANEL_ENUM = "Enum";

  /**
   * The enum panel list.
   */
  private final static String PANEL_LIST = "List";

  /**
   * The panel entries.
   */
  private JPanel panelEntries = null;

  /**
   * The document listener.
   */
  private DocumentListener documentListener = null;

  /**
   * The table model listener.
   */
  private TableModelListener tableModelListener = null;

  /**
   * The item settings panel.
   */
  private ItemSettingsPanel itemSettingsPanel = null;



  /**
   * Constructor.
   * 
   * @param gui
   *          GUI. The gui.
   * @param itemSettingsPanel
   *          The item settings panel.
   * @param documentListener
   *          The document listener.
   * @param tableModelListener
   *          The table model listener.
   */
  public ItemEntrySettingsPanel(FormEditorGUI gui, ItemSettingsPanel itemSettingsPanel, DocumentListener documentListener, TableModelListener tableModelListener)
  {
    super(gui);
    this.documentListener = documentListener;
    this.tableModelListener = tableModelListener;
    this.itemSettingsPanel = itemSettingsPanel;
  }



  /**
   * Initialise the panel.
   */
  public void initialise()
  {

    GridBagLayout layout = new GridBagLayout();
    GridBagConstraints constraints = new GridBagConstraints();
    this.setLayout(layout);

    constraints.gridx = 1;
    constraints.gridy = 1;
    constraints.gridwidth = 1;
    constraints.gridheight = 1;
    constraints.weightx = 1;
    constraints.weighty = 0;
    constraints.fill = GridBagConstraints.HORIZONTAL;
    constraints.insets = new Insets(0, 0, 0, 0);
    this.add(this.createCommonSettingsPanel(), constraints);

    this.layout = new CardLayout();
    this.panelEntries = new JPanel(this.layout);

    JPanel panelEnum = this.createPanelEnum();
    this.panelEntries.add(panelEnum, PANEL_ENUM);
    JPanel panelList = this.createPanelList();
    this.panelEntries.add(panelList, PANEL_LIST);

    constraints.gridx = 1;
    constraints.gridy = 2;
    constraints.gridwidth = 1;
    constraints.gridheight = 1;
    constraints.weightx = 1;
    constraints.weighty = 1;
    constraints.fill = GridBagConstraints.BOTH;
    constraints.insets = new Insets(5, 30, 0, 0);
    this.add(this.panelEntries, constraints);

  }



  /**
   * Create the common panel.
   * 
   * @return the common panel.
   */
  public JPanel createCommonSettingsPanel()
  {
    JPanel panel = new JPanel();

    GridBagLayout layout = new GridBagLayout();
    GridBagConstraints constraints = new GridBagConstraints();
    panel.setLayout(layout);

    this.labelEnumType = new JLabel(this.getGui().getController().notifyTranslation(Messages.ITEM_SETTINGS_ENTRY_ENUM_LABEL_TYPE));
    constraints.gridx = 1;
    constraints.gridy = 1;
    constraints.gridwidth = 1;
    constraints.gridheight = 1;
    constraints.weightx = 0;
    constraints.weighty = 0;
    constraints.fill = GridBagConstraints.HORIZONTAL;
    constraints.insets = new Insets(5, 5, 5, 5);
    panel.add(this.labelEnumType, constraints);

    this.comboEntryType = new JComboBox(new String[] { "Enumeration", "List" });
    this.comboEntryType.addActionListener(this);
    constraints.gridx = 2;
    constraints.gridy = 1;
    constraints.gridwidth = 1;
    constraints.gridheight = 1;
    constraints.weightx = 1;
    constraints.weighty = 0;
    constraints.fill = GridBagConstraints.HORIZONTAL;
    constraints.insets = new Insets(5, 0, 5, 5);
    panel.add(this.comboEntryType, constraints);

    return panel;
  }



  /**
   * Create the common panel.
   * 
   * @return the common panel.
   */
  public JPanel createPanelEnum()
  {
    JPanel panel = new JPanel();

    GridBagLayout layout = new GridBagLayout();
    GridBagConstraints constraints = new GridBagConstraints();
    panel.setLayout(layout);

    this.labelEnum = new JLabel(this.getGui().getController().notifyTranslation(Messages.ITEM_SETTINGS_ENTRY_ENUM_LABEL));
    constraints.gridx = 1;
    constraints.gridy = 1;
    constraints.gridwidth = 1;
    constraints.gridheight = 1;
    constraints.weightx = 0;
    constraints.weighty = 0;
    constraints.fill = GridBagConstraints.HORIZONTAL;
    constraints.anchor = GridBagConstraints.NORTH;
    constraints.insets = new Insets(5, 5, 5, 5);
    panel.add(this.labelEnum, constraints);

    this.textEnum = new JTextField();
    this.textEnum.getDocument().addDocumentListener(this.documentListener);
    constraints.gridx = 2;
    constraints.gridy = 1;
    constraints.gridwidth = 1;
    constraints.gridheight = 1;
    constraints.weightx = 1;
    constraints.weighty = 0;
    constraints.fill = GridBagConstraints.HORIZONTAL;
    constraints.anchor = GridBagConstraints.NORTH;
    constraints.insets = new Insets(5, 0, 5, 5);
    panel.add(this.textEnum, constraints);

    constraints.gridx = 1;
    constraints.gridy = 2;
    constraints.gridwidth = 2;
    constraints.gridheight = 1;
    constraints.weightx = 1;
    constraints.weighty = 1;
    constraints.fill = GridBagConstraints.BOTH;
    constraints.insets = new Insets(5, 5, 5, 5);
    panel.add(new JLabel(), constraints);

    return panel;
  }



  /**
   * Create the common panel.
   * 
   * @return the common panel.
   */
  public JPanel createPanelList()
  {
    JPanel panel = new JPanel();

    GridBagLayout layout = new GridBagLayout();
    GridBagConstraints constraints = new GridBagConstraints();
    panel.setLayout(layout);

    this.labelEntry = new JLabel(this.getGui().getController().notifyTranslation(Messages.ITEM_SETTINGS_ENTRY_LIST_LABEL));
    constraints.gridx = 1;
    constraints.gridy = 1;
    constraints.gridwidth = 3;
    constraints.gridheight = 1;
    constraints.weightx = 1;
    constraints.weighty = 0;
    constraints.fill = GridBagConstraints.HORIZONTAL;
    constraints.insets = new Insets(0, 0, 0, 0);
    panel.add(this.labelEntry, constraints);

    this.labelEntryName = new JLabel(this.getGui().getController().notifyTranslation(Messages.ITEM_SETTINGS_ENTRY_LIST_LABEL_NAME));
    constraints.gridx = 1;
    constraints.gridy = 2;
    constraints.gridwidth = 1;
    constraints.gridheight = 1;
    constraints.weightx = 0;
    constraints.weighty = 0;
    constraints.fill = GridBagConstraints.HORIZONTAL;
    constraints.insets = new Insets(5, 15, 0, 0);
    panel.add(this.labelEntryName, constraints);

    this.textEntryName = new JTextField();
    constraints.gridx = 2;
    constraints.gridy = 2;
    constraints.gridwidth = 1;
    constraints.gridheight = 1;
    constraints.weightx = 1;
    constraints.weighty = 0;
    constraints.fill = GridBagConstraints.HORIZONTAL;
    constraints.insets = new Insets(5, 5, 0, 0);
    panel.add(this.textEntryName, constraints);

    this.buttonAddEntry = new JButton(this.getGui().getController().notifyTranslation(Messages.ITEM_SETTINGS_ENTRY_LIST_BUTTON_ADD));
    this.buttonAddEntry.addActionListener(this);
    constraints.gridx = 3;
    constraints.gridy = 2;
    constraints.gridwidth = 1;
    constraints.gridheight = 1;
    constraints.weightx = 0;
    constraints.weighty = 0;
    constraints.fill = GridBagConstraints.NONE;
    constraints.insets = new Insets(5, 5, 0, 0);
    panel.add(this.buttonAddEntry, constraints);

    String[] columnNames = new String[] { this.getGui().getController().notifyTranslation(Messages.ITEM_SETTINGS_ENTRY_LIST_TABLE_NAME),
        this.getGui().getController().notifyTranslation(Messages.ITEM_SETTINGS_ENTRY_LIST_TABLE_VALUE) };
    this.tableEntriesModel = new VariableTableModel(columnNames);
    this.tableEntriesModel.addTableModelListener(this.tableModelListener);
    this.tableEntries = new JTable(this.tableEntriesModel);
    this.tableEntries.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
    VariableCellRenderer cellRenderer = new VariableCellRenderer(this.getGui());
    VariableCellEditor cellEditor = new VariableCellEditor(this.getGui());
    this.tableEntries.getColumnModel().getColumn(0).setCellRenderer(cellRenderer);
    this.tableEntries.getColumnModel().getColumn(1).setCellRenderer(cellRenderer);
    this.tableEntries.getColumnModel().getColumn(0).setCellEditor(cellEditor);
    this.tableEntries.getColumnModel().getColumn(1).setCellEditor(cellEditor);
    this.tableEntries.setRowHeight(25);
    JScrollPane scrollpane = new JScrollPane(this.tableEntries);
    constraints.gridx = 1;
    constraints.gridy = 3;
    constraints.gridwidth = 3;
    constraints.gridheight = 1;
    constraints.weightx = 1;
    constraints.weighty = 1;
    constraints.fill = GridBagConstraints.BOTH;
    constraints.insets = new Insets(5, 15, 0, 0);
    panel.add(scrollpane, constraints);

    this.buttonDeleteSelectedEntry = new JButton(this.getGui().getController().notifyTranslation(Messages.ITEM_SETTINGS_ENTRY_LIST_BUTTON_DELETE));
    this.buttonDeleteSelectedEntry.addActionListener(this);
    constraints.gridx = 1;
    constraints.gridy = 4;
    constraints.gridwidth = 3;
    constraints.gridheight = 1;
    constraints.weightx = 0;
    constraints.weighty = 0;
    constraints.fill = GridBagConstraints.NONE;
    constraints.anchor = GridBagConstraints.EAST;
    constraints.insets = new Insets(5, 0, 0, 0);
    panel.add(this.buttonDeleteSelectedEntry, constraints);

    return panel;
  }



  /**
   * Handle the action event.
   * 
   * @param e
   *          the action event.
   */
  public void actionPerformed(ActionEvent e)
  {
    Object source = e.getSource();
    if (source.equals(this.buttonAddEntry)) {
      String name = this.textEntryName.getText();
      boolean alreadyExists = false;
      for (VariableModel variable : this.tableEntriesModel.getVariables()) {
        if (variable.getName().equals(name)) {
          alreadyExists = true;
        }
      }
      if (!alreadyExists) {
        if (name != null && name.trim().length() > 0) {
          this.tableEntriesModel.addVariable(new VariableModel(name, ""));
        }
        this.textEntryName.setText("");
      }
      else {
        this.getGui().tell(this.getGui().getController().notifyTranslation(Messages.ITEM_SETTINGS_ENTRY_LIST_ERROR_DELETE_TITLE),
            this.getGui().getController().notifyTranslation(Messages.ITEM_SETTINGS_ENTRY_LIST_ERROR_DELETE_MESSAGE));
        this.textEntryName.setText("");
      }
    }
    else if (source.equals(this.buttonDeleteSelectedEntry)) {
      int row = this.tableEntries.getSelectedRow();
      if (row != -1) {
        VariableModel variable = this.tableEntriesModel.getValueAt(row);
        if (variable != null && !variable.isMandatory()) {
          if (this.getGui().ask(this.getGui().getController().notifyTranslation(Messages.ITEM_SETTINGS_ENTRY_LIST_ERROR_CREATE_TITLE),
              this.getGui().getController().notifyTranslation(Messages.ITEM_SETTINGS_ENTRY_LIST_ERROR_CREATE_MESSAGE))) {
            this.tableEntriesModel.removeVariable(variable);
          }
        }
      }
    }
    else if (source.equals(this.comboEntryType)) {
      String value = (String) this.comboEntryType.getSelectedItem();
      if (value.compareTo("Enumeration") == 0) {
        this.cleanPanelList();
        this.layout.show(this.panelEntries, PANEL_ENUM);
      }
      else {
        this.cleanPanelEnum();
        this.layout.show(this.panelEntries, PANEL_LIST);
      }
      this.itemSettingsPanel.notifyChanges();
    }
  }



  /**
   * Clean the list panel.
   */
  private void cleanPanelList()
  {
    this.textEntryName.setText("");
  }



  /**
   * Clean the enum panel.
   */
  private void cleanPanelEnum()
  {
    this.textEnum.setText("");
  }



  /**
   * Get the enumeration.
   * 
   * @return the enumeration.
   */
  public String getEnumeration()
  {
    String enumeration = this.textEnum.getText();
    if (enumeration == null || enumeration.trim().length() == 0) {
      enumeration = null;
    }
    return enumeration;
  }



  /**
   * Get the entries.
   * 
   * @return the entries.
   */
  public List<VariableModel> getEntries()
  {
    return this.tableEntriesModel.getVariables();
  }



  /**
   * Set the displayed values.
   * 
   * @param enumeration
   *          The enumeration.
   * @param entries
   *          The entries.
   */
  public void setDisplayedValues(String enumeration, List<VariableModel> entries)
  {
    this.cleanPanelEnum();
    this.cleanPanelList();
    this.comboEntryType.removeActionListener(this);
    if (enumeration == null || enumeration.trim().length() == 0) {
      this.layout.show(this.panelEntries, PANEL_LIST);
      this.comboEntryType.setSelectedItem("List");
      this.tableEntriesModel.setVariables(entries);
      this.tableEntriesModel.fireTableDataChanged();
    }
    else {
      this.layout.show(this.panelEntries, PANEL_ENUM);
      this.comboEntryType.setSelectedItem("Enumeration");
      this.textEnum.setText(enumeration);
    }
    this.comboEntryType.addActionListener(this);
  }



  /**
   * Check whether the settings are valid.
   */
  public void validateSettings()
  {
    String type = (String) this.comboEntryType.getSelectedItem();
    if (type.compareTo("Enumeration") == 0) {
      boolean isOK = !(this.textEnum.getText() == null || this.textEnum.getText().trim().length() == 0);
      if (isOK) {
        EnumDescriptableValuedItemEntryListImpl entries;
        try {
          EnumDescriptableValuedItemEntryListFactory entriesFactory = new EnumDescriptableValuedItemEntryListFactory();
          entriesFactory.setEnumClassName(this.textEnum.getText());
          entries = (EnumDescriptableValuedItemEntryListImpl) entriesFactory.getObject();
          if (entries == null) {
            isOK = false;
          }
        }
        catch (Exception e) {
          isOK = false;
        }
      }
      if (!isOK) {
        this.labelEnum.setForeground(AbstractGUI.COLOR_TEXT_ERROR);
      }
      else {
        this.labelEnum.setForeground(AbstractGUI.COLOR_TEXT);
      }
    }
  }

}
